Repository navigation
feat(mcp): trade intelligence tools - #417
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7943a70631
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a0060aa420
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7355600e77
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8f90d4f150
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
42a2d47 to
ac83315
Compare
91cfe8f to
61e6fe0
Compare
Seven read-only tools for US ocean import market data, built on the SDK's tradeIntel namespace: search_importers, get_importer_profile, search_commodities, rank_importers, get_trade_trends, get_trade_breakdown, and get_trade_data_coverage. Record-level container and bill of lading lookups stay in the SDK only. The tool descriptions and server instructions carry the caveats agents got wrong without guidance: search ranks by match not size and splits companies by state, the profile with months: 24 is the way to get one company's trend (the trends company filter is a substring match), trends and breakdowns include the incomplete current month, history starts in January 2022, missing volume can mean withheld names, values are estimates, and volumes don't add across products or companies. Inputs are strict (enums for measure, interval, dimensions, and coast; real YYYY-MM months; bounded limits). A 403 returns a plain "not enabled, contact support@terminal49.com" result instead of an error; 400 shows the API's reason, and 429 and 5xx get plain messages without internals. Responses drop internal fields, round numbers, cap long lists, and flag truncation. Adds unit and server tests, eval cases that pass with or without the feature, the new tools in both store listings, and an Unreleased changelog entry. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Adds a trade intelligence section to the MCP tools reference with each tool's parameters, example questions, the per-account enablement note, and the caveats for reading the numbers. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- A high notify-party share is a clue, not proof of a forwarder: large cargo owners can be mostly notify party, so the descriptions and instructions now say to weigh the name and product mix too. - Name and filter inputs accept up to 200 characters, matching the API, so a long company name from search can be reused in later calls. - search_importers reports more_not_shown when it cuts a row's ports, origins, carriers, or products to five, and search_commodities keeps up to 15 common goods and counts the rest in common_goods_not_shown. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Push-time CI runs the live eval against production, which doesn't list tools a PR adds until it deploys. The new cases now skip when the server under test doesn't list the tool, and still run against the PR preview. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…airly - search_importers results cover the search index's 12-month window, which can end a month or two before the last full month. The period note, min_containers, and the tool description now say so and point to get_importer_profile for the latest months. - Eval cases for account-gated tools score a "not enabled" reply as the allowed outcome it is, so the scorecard and report no longer count it as a contract failure. Adds unit tests for that scorer. Raised in the Codex and Greptile reviews on the PR. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…evels Trend points arrive ordered by period then group, so cutting the flat series at 500 dropped the newest periods and could split one, while the reported range still claimed them. The series now keeps the most recent whole periods, reports the range actually returned, and counts the earlier periods left out. Breakdowns drop whole deeper levels instead of cutting a parent's children. Raised in Codex review on the PR. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The trends and breakdown defaults run from about two years (or one year) back through the current, incomplete month, inclusive, so they are not a clean 24 or 12 months. Descriptions now say so and tell agents to set since and until for annual totals. min_containers applies to the search window in period, not the last 12 full months. Raised in Codex review on the PR. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A capped quarterly or yearly series reported a range mixing a point label (2026-Q1) with a month boundary (2026-06). period now always holds the requested month range, and periods_shown gives the first and last periods actually returned, in the series' own labels. Raised in Codex review on the PR. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
20f6583 to
48d89a1
Compare
* feat(mcp): add trade intelligence tools Seven read-only tools for US ocean import market data, built on the SDK's tradeIntel namespace: search_importers, get_importer_profile, search_commodities, rank_importers, get_trade_trends, get_trade_breakdown, and get_trade_data_coverage. Record-level container and bill of lading lookups stay in the SDK only. The tool descriptions and server instructions carry the caveats agents got wrong without guidance: search ranks by match not size and splits companies by state, the profile with months: 24 is the way to get one company's trend (the trends company filter is a substring match), trends and breakdowns include the incomplete current month, history starts in January 2022, missing volume can mean withheld names, values are estimates, and volumes don't add across products or companies. Inputs are strict (enums for measure, interval, dimensions, and coast; real YYYY-MM months; bounded limits). A 403 returns a plain "not enabled, contact support@terminal49.com" result instead of an error; 400 shows the API's reason, and 429 and 5xx get plain messages without internals. Responses drop internal fields, round numbers, cap long lists, and flag truncation. Adds unit and server tests, eval cases that pass with or without the feature, the new tools in both store listings, and an Unreleased changelog entry. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * docs(mcp): document the trade intelligence tools Adds a trade intelligence section to the MCP tools reference with each tool's parameters, example questions, the per-account enablement note, and the caveats for reading the numbers. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(mcp): address Codex review of the trade intelligence tools - A high notify-party share is a clue, not proof of a forwarder: large cargo owners can be mostly notify party, so the descriptions and instructions now say to weigh the name and product mix too. - Name and filter inputs accept up to 200 characters, matching the API, so a long company name from search can be reused in later calls. - search_importers reports more_not_shown when it cuts a row's ports, origins, carriers, or products to five, and search_commodities keeps up to 15 common goods and counts the rest in common_goods_not_shown. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * docs(mcp): qualify the notify-party signal and the common goods cap Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * test(mcp): skip trade intelligence evals where the tools aren't deployed Push-time CI runs the live eval against production, which doesn't list tools a PR adds until it deploys. The new cases now skip when the server under test doesn't list the tool, and still run against the PR preview. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(mcp): describe the search window honestly and score gated evals fairly - search_importers results cover the search index's 12-month window, which can end a month or two before the last full month. The period note, min_containers, and the tool description now say so and point to get_importer_profile for the latest months. - Eval cases for account-gated tools score a "not enabled" reply as the allowed outcome it is, so the scorecard and report no longer count it as a contract failure. Adds unit tests for that scorer. Raised in the Codex and Greptile reviews on the PR. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * docs(mcp): spell out TEU and HS, and describe the search window Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(mcp): cap trend series by whole periods and breakdowns by whole levels Trend points arrive ordered by period then group, so cutting the flat series at 500 dropped the newest periods and could split one, while the reported range still claimed them. The series now keeps the most recent whole periods, reports the range actually returned, and counts the earlier periods left out. Breakdowns drop whole deeper levels instead of cutting a parent's children. Raised in Codex review on the PR. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(mcp): describe default windows and min_containers precisely The trends and breakdown defaults run from about two years (or one year) back through the current, incomplete month, inclusive, so they are not a clean 24 or 12 months. Descriptions now say so and tell agents to set since and until for annual totals. min_containers applies to the search window in period, not the last 12 full months. Raised in Codex review on the PR. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * docs(mcp): describe the trends and breakdown default windows precisely Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(mcp): keep a capped trend's range in one period format A capped quarterly or yearly series reported a range mixing a point label (2026-Q1) with a month boundary (2026-06). period now always holds the requested month range, and periods_shown gives the first and last periods actually returned, in the series' own labels. Raised in Codex review on the PR. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* feat(mcp): add trade intelligence tools Seven read-only tools for US ocean import market data, built on the SDK's tradeIntel namespace: search_importers, get_importer_profile, search_commodities, rank_importers, get_trade_trends, get_trade_breakdown, and get_trade_data_coverage. Record-level container and bill of lading lookups stay in the SDK only. The tool descriptions and server instructions carry the caveats agents got wrong without guidance: search ranks by match not size and splits companies by state, the profile with months: 24 is the way to get one company's trend (the trends company filter is a substring match), trends and breakdowns include the incomplete current month, history starts in January 2022, missing volume can mean withheld names, values are estimates, and volumes don't add across products or companies. Inputs are strict (enums for measure, interval, dimensions, and coast; real YYYY-MM months; bounded limits). A 403 returns a plain "not enabled, contact support@terminal49.com" result instead of an error; 400 shows the API's reason, and 429 and 5xx get plain messages without internals. Responses drop internal fields, round numbers, cap long lists, and flag truncation. Adds unit and server tests, eval cases that pass with or without the feature, the new tools in both store listings, and an Unreleased changelog entry. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * docs(mcp): document the trade intelligence tools Adds a trade intelligence section to the MCP tools reference with each tool's parameters, example questions, the per-account enablement note, and the caveats for reading the numbers. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(mcp): address Codex review of the trade intelligence tools - A high notify-party share is a clue, not proof of a forwarder: large cargo owners can be mostly notify party, so the descriptions and instructions now say to weigh the name and product mix too. - Name and filter inputs accept up to 200 characters, matching the API, so a long company name from search can be reused in later calls. - search_importers reports more_not_shown when it cuts a row's ports, origins, carriers, or products to five, and search_commodities keeps up to 15 common goods and counts the rest in common_goods_not_shown. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * docs(mcp): qualify the notify-party signal and the common goods cap Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * test(mcp): skip trade intelligence evals where the tools aren't deployed Push-time CI runs the live eval against production, which doesn't list tools a PR adds until it deploys. The new cases now skip when the server under test doesn't list the tool, and still run against the PR preview. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(mcp): describe the search window honestly and score gated evals fairly - search_importers results cover the search index's 12-month window, which can end a month or two before the last full month. The period note, min_containers, and the tool description now say so and point to get_importer_profile for the latest months. - Eval cases for account-gated tools score a "not enabled" reply as the allowed outcome it is, so the scorecard and report no longer count it as a contract failure. Adds unit tests for that scorer. Raised in the Codex and Greptile reviews on the PR. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * docs(mcp): spell out TEU and HS, and describe the search window Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(mcp): cap trend series by whole periods and breakdowns by whole levels Trend points arrive ordered by period then group, so cutting the flat series at 500 dropped the newest periods and could split one, while the reported range still claimed them. The series now keeps the most recent whole periods, reports the range actually returned, and counts the earlier periods left out. Breakdowns drop whole deeper levels instead of cutting a parent's children. Raised in Codex review on the PR. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(mcp): describe default windows and min_containers precisely The trends and breakdown defaults run from about two years (or one year) back through the current, incomplete month, inclusive, so they are not a clean 24 or 12 months. Descriptions now say so and tell agents to set since and until for annual totals. min_containers applies to the search window in period, not the last 12 full months. Raised in Codex review on the PR. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * docs(mcp): describe the trends and breakdown default windows precisely Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(mcp): keep a capped trend's range in one period format A capped quarterly or yearly series reported a range mixing a point label (2026-Q1) with a month boundary (2026-06). period now always holds the requested month range, and periods_shown gives the first and last periods actually returned, in the series' own labels. Raised in Codex review on the PR. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* feat(mcp): add trade intelligence tools Seven read-only tools for US ocean import market data, built on the SDK's tradeIntel namespace: search_importers, get_importer_profile, search_commodities, rank_importers, get_trade_trends, get_trade_breakdown, and get_trade_data_coverage. Record-level container and bill of lading lookups stay in the SDK only. The tool descriptions and server instructions carry the caveats agents got wrong without guidance: search ranks by match not size and splits companies by state, the profile with months: 24 is the way to get one company's trend (the trends company filter is a substring match), trends and breakdowns include the incomplete current month, history starts in January 2022, missing volume can mean withheld names, values are estimates, and volumes don't add across products or companies. Inputs are strict (enums for measure, interval, dimensions, and coast; real YYYY-MM months; bounded limits). A 403 returns a plain "not enabled, contact support@terminal49.com" result instead of an error; 400 shows the API's reason, and 429 and 5xx get plain messages without internals. Responses drop internal fields, round numbers, cap long lists, and flag truncation. Adds unit and server tests, eval cases that pass with or without the feature, the new tools in both store listings, and an Unreleased changelog entry. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * docs(mcp): document the trade intelligence tools Adds a trade intelligence section to the MCP tools reference with each tool's parameters, example questions, the per-account enablement note, and the caveats for reading the numbers. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(mcp): address Codex review of the trade intelligence tools - A high notify-party share is a clue, not proof of a forwarder: large cargo owners can be mostly notify party, so the descriptions and instructions now say to weigh the name and product mix too. - Name and filter inputs accept up to 200 characters, matching the API, so a long company name from search can be reused in later calls. - search_importers reports more_not_shown when it cuts a row's ports, origins, carriers, or products to five, and search_commodities keeps up to 15 common goods and counts the rest in common_goods_not_shown. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * docs(mcp): qualify the notify-party signal and the common goods cap Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * test(mcp): skip trade intelligence evals where the tools aren't deployed Push-time CI runs the live eval against production, which doesn't list tools a PR adds until it deploys. The new cases now skip when the server under test doesn't list the tool, and still run against the PR preview. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(mcp): describe the search window honestly and score gated evals fairly - search_importers results cover the search index's 12-month window, which can end a month or two before the last full month. The period note, min_containers, and the tool description now say so and point to get_importer_profile for the latest months. - Eval cases for account-gated tools score a "not enabled" reply as the allowed outcome it is, so the scorecard and report no longer count it as a contract failure. Adds unit tests for that scorer. Raised in the Codex and Greptile reviews on the PR. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * docs(mcp): spell out TEU and HS, and describe the search window Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(mcp): cap trend series by whole periods and breakdowns by whole levels Trend points arrive ordered by period then group, so cutting the flat series at 500 dropped the newest periods and could split one, while the reported range still claimed them. The series now keeps the most recent whole periods, reports the range actually returned, and counts the earlier periods left out. Breakdowns drop whole deeper levels instead of cutting a parent's children. Raised in Codex review on the PR. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(mcp): describe default windows and min_containers precisely The trends and breakdown defaults run from about two years (or one year) back through the current, incomplete month, inclusive, so they are not a clean 24 or 12 months. Descriptions now say so and tell agents to set since and until for annual totals. min_containers applies to the search window in period, not the last 12 full months. Raised in Codex review on the PR. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * docs(mcp): describe the trends and breakdown default windows precisely Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(mcp): keep a capped trend's range in one period format A capped quarterly or yearly series reported a range mixing a point label (2026-Q1) with a month boundary (2026-06). period now always holds the requested month range, and periods_shown gives the first and last periods actually returned, in the series' own labels. Raised in Codex review on the PR. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…415) * docs: add Trade Intelligence endpoints to the API reference Documents the nine /v2/trade_intel endpoints (US import bill-of-lading records from US Customs manifests, January 2022 onward) under a public Trade Intelligence tag: request and response schemas as TradeIntel* components, the 400/401/403/422/429/502/504 error bodies, and endpoint descriptions that carry the data caveats (physical containers, estimated values, partial current month, names split by state or withheld, substring company filter, carrier spelling variants). Adds the reference pages to the API Reference navigation and regenerates the Postman collection. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat(sdk): add tradeIntel namespace for trade intelligence client.tradeIntel exposes meta, searchCompanies, companyProfile, searchCommodities, topImporters, trends, breakdown, lookupContainer, and lookupBillOfLading. They return the endpoints' plain JSON bodies with types generated from docs/openapi.json, and surface errors through the existing error types: the 403 "not enabled" body maps to FeatureNotEnabledError, 400 and 422 (including FastAPI detail arrays) to ValidationError. The trade intelligence POSTs are read-only queries, so the retry policy now treats POSTs under /trade_intel/ like GETs: 429, 5xx, and network failures are retried with backoff. Other writes still need an Idempotency-Key. Types are generated with --default-non-nullable=false so request fields with server defaults (limit, months, top) stay optional; no existing type changes. Fixture-based tests cover every method (path, method, body, response passthrough) and the 400/422/403/429/502 paths. Regenerates the SDK reference docs and documents the namespace. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * docs: state the real commodity ordering in trade intelligence lookups Lookups sort commodity lines by bill, then by estimated value within each bill, and the 200-line cap applies to that order. The schemas promised a global highest-value-first order, which a multi-bill response does not give. Found in Codex review. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * docs: mark always-returned trade intelligence response fields required meta, the companies/search results, commodities/search results, trend points, and top importers always carry these fields in production, so the generated SDK types no longer make them optional. Fields that are conditional stay optional: a trend point's partial flag, a ranking's estimated_value without hs4, and a profile's details when found is false. Raised in Codex review on the PR. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * chore(sdk): regenerate types and reference for required response fields Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * docs: restrict trade intelligence month fields to real calendar months since and until in trends and breakdown accepted any two-digit month, so schema-validating clients and generated Postman examples allowed values like 2026-60. Raised in Codex review on the PR. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat(mcp): trade intelligence tools (#417) * feat(mcp): add trade intelligence tools Seven read-only tools for US ocean import market data, built on the SDK's tradeIntel namespace: search_importers, get_importer_profile, search_commodities, rank_importers, get_trade_trends, get_trade_breakdown, and get_trade_data_coverage. Record-level container and bill of lading lookups stay in the SDK only. The tool descriptions and server instructions carry the caveats agents got wrong without guidance: search ranks by match not size and splits companies by state, the profile with months: 24 is the way to get one company's trend (the trends company filter is a substring match), trends and breakdowns include the incomplete current month, history starts in January 2022, missing volume can mean withheld names, values are estimates, and volumes don't add across products or companies. Inputs are strict (enums for measure, interval, dimensions, and coast; real YYYY-MM months; bounded limits). A 403 returns a plain "not enabled, contact support@terminal49.com" result instead of an error; 400 shows the API's reason, and 429 and 5xx get plain messages without internals. Responses drop internal fields, round numbers, cap long lists, and flag truncation. Adds unit and server tests, eval cases that pass with or without the feature, the new tools in both store listings, and an Unreleased changelog entry. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * docs(mcp): document the trade intelligence tools Adds a trade intelligence section to the MCP tools reference with each tool's parameters, example questions, the per-account enablement note, and the caveats for reading the numbers. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(mcp): address Codex review of the trade intelligence tools - A high notify-party share is a clue, not proof of a forwarder: large cargo owners can be mostly notify party, so the descriptions and instructions now say to weigh the name and product mix too. - Name and filter inputs accept up to 200 characters, matching the API, so a long company name from search can be reused in later calls. - search_importers reports more_not_shown when it cuts a row's ports, origins, carriers, or products to five, and search_commodities keeps up to 15 common goods and counts the rest in common_goods_not_shown. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * docs(mcp): qualify the notify-party signal and the common goods cap Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * test(mcp): skip trade intelligence evals where the tools aren't deployed Push-time CI runs the live eval against production, which doesn't list tools a PR adds until it deploys. The new cases now skip when the server under test doesn't list the tool, and still run against the PR preview. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(mcp): describe the search window honestly and score gated evals fairly - search_importers results cover the search index's 12-month window, which can end a month or two before the last full month. The period note, min_containers, and the tool description now say so and point to get_importer_profile for the latest months. - Eval cases for account-gated tools score a "not enabled" reply as the allowed outcome it is, so the scorecard and report no longer count it as a contract failure. Adds unit tests for that scorer. Raised in the Codex and Greptile reviews on the PR. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * docs(mcp): spell out TEU and HS, and describe the search window Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(mcp): cap trend series by whole periods and breakdowns by whole levels Trend points arrive ordered by period then group, so cutting the flat series at 500 dropped the newest periods and could split one, while the reported range still claimed them. The series now keeps the most recent whole periods, reports the range actually returned, and counts the earlier periods left out. Breakdowns drop whole deeper levels instead of cutting a parent's children. Raised in Codex review on the PR. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(mcp): describe default windows and min_containers precisely The trends and breakdown defaults run from about two years (or one year) back through the current, incomplete month, inclusive, so they are not a clean 24 or 12 months. Descriptions now say so and tell agents to set since and until for annual totals. min_containers applies to the search window in period, not the last 12 full months. Raised in Codex review on the PR. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * docs(mcp): describe the trends and breakdown default windows precisely Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(mcp): keep a capped trend's range in one period format A capped quarterly or yearly series reported a range mixing a point label (2026-Q1) with a month boundary (2026-06). period now always holds the requested month range, and periods_shown gives the first and last periods actually returned, in the series' own labels. Raised in Codex review on the PR. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * chore: regenerate SDK types, SDK reference docs, and Postman collection Regenerated once on top of main after the rebase (main's SDK resync in Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * docs: state which trade intelligence dimensions can't be combined Lane dimensions (pol, pol_country, container_type) can't be combined with company or product dimensions in one request, and estimated_value isn't available by them; the API answers 400. The MCP tool descriptions said so but the API reference didn't. Raised in Codex review on the PR. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * docs: merge trade intelligence responses into the shared responses block Main's spec now declares components.responses (#438), and the rebase's text merge added the trade intelligence block as a second "responses" key in the same object. JSON parsers keep the last key, but YAML-strict tooling such as openapi-typescript rejects the duplicate. Both sets now live in one block. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(sdk): let tradeIntel calls infer their types from the spec Transport.execute now infers the response body type from the typed openapi-fetch call (#439), so the explicit body type arguments no longer fit its signature. The inferred types are the same TradeIntel* schemas. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * chore: regenerate SDK types, SDK reference docs, and Postman collection Regenerated on top of main after #438 and #439. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * docs: require exact-length trade intelligence state, SCAC and HS4 codes State filters (company_state, dest_state, state) now require two letters, the scac filter four letters, and top importers hs4 four digits, matching the MCP tool schemas. maxLength alone let values like "F" or "123" through. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(sdk): keep the RetryInterceptor doc comment on the class The retry explanation sat above the new ReplayableRequest and RetryRequestParams declarations, so the generated reference lost it. Move it back above RetryInterceptor and say that read-only trade intelligence query POSTs are retried like GETs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore: regenerate SDK reference docs and Postman collection Regenerated after the trade intelligence code patterns and the RetryInterceptor doc comment move. SDK types and MCP filter schemas are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore: Auto-generate Postman collection from openapi.json [skip ci] * docs(mcp): say estimated_value is not available by lane The API rejects estimated_value with pol, pol_country or container_type as a dimension or filter (docs/openapi.json TradeIntelDimension and TradeIntelFilters). The MCP guide presented estimated_value as generally available, so it now states the restriction for get_trade_trends and get_trade_breakdown and lists the lane combination rules with the other trade intelligence caveats. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(mcp): warn that estimated_value is not available by lane The measure and dimension descriptions for get_trade_trends and get_trade_breakdown now say that estimated_value cannot be used with pol, pol_country or container_type, which the API answers with a 400. A protocol test checks the advertised measure description and the MCP docs section for both tools. Addresses the Codex review on packages/mcp/src/tools/trade-intel.ts:82. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(mcp): count all 21 tools in the README, overview and setup guide The PR registers seven trade intelligence tools, but the MCP README header and table, the TOOLS_OVERVIEW summary and the setup guide's "list the tools" check still said 14. The README table now lists the trade intelligence tools too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(mcp): keep documented tool counts and the README table on tools/list Fails when the README, TOOLS_OVERVIEW or the setup guide state a tool count other than the tools/list length, or when the README tool table misses or adds a tool. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(mcp): require the lane-filter case in the estimated_value warning The API rejects estimated_value when pol, pol_country or container_type is used at all, as a dimension or as a filter. The test now fails if the tool description or the docs drop the filter case. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(mcp): pin the trade trends and breakdown default windows Without since, the trade-intel service returns the N months ending with until (24 for trends, 12 for breakdown), so since is N - 1 months before until. The test fails while tools/list, docs/mcp/home.mdx or the OpenAPI spec describe the default as "N months ago" or "about a year back". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(trade-intel): state the trends and breakdown default windows exactly Without since, the API returns the N months ending with until (24 for trends, 12 for breakdown), so since defaults to N - 1 months before until. The since fields said "Defaults to 24/12 months ago", which reads as N + 1 calendar months. The breakdown and trends descriptions and the MCP guide now give the same window. Source: analytics._range in the trade-intel service. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore: Auto-generate Postman collection from openapi.json [skip ci] * fix(mcp,sdk): describe the trade default windows as the API computes them get_trade_trends and get_trade_breakdown said "about two years back" and "about a year back, not a clean 12 months". They now say the window is the 24 or 12 months ending with the current, incomplete month, with since 23 or 11 months before until. The SDK JSDoc, regenerated types and SDK reference match the OpenAPI source. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(openapi): match the trade intelligence contract to what the service returns Checked against Terminal49/t49 staging (apps/trade-intel build.py, analytics.py, api.py, index.py): - meta dates (since_month, until_month_exclusive, facts_since_month, partial_month, refreshed_since) and company first_month/last_month are first-of-month dates, YYYY-MM-DD; facts_until_exclusive is the day after the build; mode is full or incremental. - importers/top: states can be null, estimated_value is always sent and is null without hs4, and filters echo port_of_discharge as pod. - companies/profile: until is absent when found is false, and totals.states can be null. - trends periods are always YYYY-MM (the first month of the quarter or year), not YYYY-Qn or YYYY. - a 422 can also be the query cost-cap error, { error }. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(sdk): type trade intelligence nulls and keep retries within maxRetries Regenerated types from the corrected spec, so TradeIntelTopImporter states and estimated_value, profile totals.states and profile until are typed as the service sends them, ranking filters expose pod, and the 422 body includes the cost-cap { error } variant. Type tests in spec-types.test.ts fail against the old types. Fixtures now use the service's real formats (YYYY-MM-DD meta dates, YYYY-MM quarterly periods), and the live smoke test expects facts_since_month as a first-of-month date. RetryInterceptor kept separate retry counters in onError and onResponse, so network failure, network failure, 503, 503, success made five requests with maxRetries 2. Both paths now draw on one per-request budget. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore: Auto-generate Postman collection from openapi.json [skip ci] * fix(mcp): read the trade index dates the service actually sends The service sends meta and search-window dates as YYYY-MM-DD, but previousMonth() only accepted YYYY-MM, so get_trade_data_coverage lost last_full_month and search_window.to, and search_importers lost period.to. Index dates are now accepted in either form and shown as YYYY-MM, including first_month and last_month. rank_importers also leaves out estimated_value_usd when the service sends null instead of emitting an undefined key. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Summary
Adds seven read-only trade intelligence tools to the Terminal49 MCP server. They are built on
client.tradeIntelfrom #415, so this PR is stacked onfeat/trade-intel-sdk. Retarget it tomainonce #415 merges.search_importersget_importer_profilesearch_commoditiesrank_importersget_trade_trendsget_trade_breakdownget_trade_data_coverageThe container and bill of lading lookups stay in the SDK only. They return other companies' shipment-level parties, so they are not exposed through MCP.
What to review
months: 24for one company's trend; the trendscompanyfilter is a substring match.YYYY-MMmonths, and bounded limits. String limits match the API's 200 characters.more_not_shownorcommon_goods_not_showncounts, and series and rows are capped with atruncatedflag.Test evidence
found: falseshapes, the 403 path for all seven tools, and error formatting.vp run checkreported 0 errors.vp run testandvp run buildpass, andeval:checkand lint pass.initializeandtools/listshow 20 tools with the new schemas. The protocol smoke passes on 2026-07-28 and 2024-11-05.tools/callofget_trade_data_coveragereached production with the local token. That account lacks trade intelligence, so it returned the plain not-enabled message. An invalid month was rejected by the schema before any API call. A successful live data call still needs a token from an enabled account.Stack, merge order, and owner prerequisites
This PR is part of a two-PR stack: #415 (OpenAPI + SDK, into
main), then #417 (MCP tools, stacked onfeat/trade-intel-sdk). Nothing here is auto-merged, published, or deployed.Reviewers: @maurycy for code on both PRs; @namitabhasin for the public API reference docs in #415. One #415 thread stays open on purpose for the reviewer: whether to type
latest_importin the container lookup. Nothing documents that object's fields, so it is left open-ended.Steps, each needing an owner's go-ahead:
main. This publishes the Trade Intelligence API reference on the public docs site through Mintlify. The handoff asked for public pages, but the merge makes it live. Vercel also rebuilds the MCP gateway frommain. Its tools are unchanged, since MCP only uses the SDK's new retry rule for/trade_intel/paths, which no existing tool calls. The Postman workflow will push its usual auto-generated collection commit tomain.@terminal49/sdkpin inpackages/mcpand the CLI. Merging that release PR triggers the npm publish of@terminal49/sdk, which needs explicit approval. The MCP server builds from the workspace SDK, so it does not need the npm publish.mainfirst, so the SDK commits don't show twice:mainalso enables the pull-request CI jobs, including the Vercel-preview HTTP smoke and eval. Until then, feat(mcp): trade intelligence tools #417's CI ran through push builds of thefeature/trade-intel-mcpmirror branch, which has the same commit SHAs.main. This deploys the seven tools to production at mcp.terminal49.com through Vercel, which needs explicit approval. Afterwards, edit the Claude directory listing's tool names in the portal, let the ChatGPT directory rescan the tools, and cut the usualrelease(mcp)version PR. feat(mcp): trade intelligence tools #417 only adds an Unreleased changelog entry.Credentials needed for full live verification:
401 invalid API token, so it needs replacing.MCP_EVAL_TOKENCI secret has trade intelligence, the preview evals will exercise real data. Otherwise they accept the not-enabled reply.Already verified against #417's preview deployment, at the branch alias for head
91cfe8f: the HTTP protocol smoke passes on 2026-07-28 and 2025-11-25, with 20 tools listed. Running the eval suite there with the revoked key fails only on that401. Production fails the same way with that key.🤖 Generated with Claude Code
Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.The PR appears safe to merge, with a non-blocking fix needed for misleading eval reports on disabled accounts.
Fix with agent prompt
Summary
Adds seven read-only tools for US import market research through
client.tradeIntel.Diagram
%%{init: {'theme': 'neutral'}}%% flowchart LR C[MCP client] --> T[Seven trade intelligence tools] T --> V[Check inputs] V --> S[SDK tradeIntel] S --> A[Terminal49 API] A --> G{Feature enabled?} G -->|No| N[Plain not-enabled reply] G -->|Yes| R[Round numbers and cap lists] R --> O[Structured data and text] N --> C O --> CReviews (1) · Last reviewed commit: "docs(mcp): qualify the notify-party sign..." · Reviewed by Greptile
Current readiness verification keeps the original gates. Local checks and tests pass, but authenticated MCP preview evaluation is blocked by a backend HTTP 401 for the shared CI passthrough credential. The transport handshake alone does not prove tool access. Review fixes and rebases preserve this PR's base topology. No merge or deploy has been performed.